package cn.com.taiji.oospub.wechat.common.util;

import cn.com.taiji.oospub.wechat.common.JsonDateValueProcessor;
import cn.com.taiji.oospub.wechat.common.Node;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.DefaultValueProcessor;
import net.sf.json.util.CycleDetectionStrategy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.*;
  
/**
 * 
 * @ClassName: JsonUtil
 * @Description: Json帮助类
 * @author sunwei Email： sunwei@mail.taiji.com.cn
 * @date 2012-8-6 - 下午12:12:17
 *@version : 1.0
 */
public class JsonUtil {  
    
    private static Log log = null;

    private StringBuffer returnStr=new StringBuffer();
    static {
        
        setJsonDataFormat();
        log = LogFactory.getLog(JsonUtil.class);
    }
    
    public static JSONObject getJSONObject(String jsonString) {
        JSONObject jsonObject = null;   
        try {    
            log.debug("json: " + jsonString);
            jsonObject = JSONObject.fromObject(jsonString);   
        } catch(Exception e) {   
            e.printStackTrace();   
        }
        return jsonObject;
    }

    public static JSONObject getJSONObject(String jsonString, JsonConfig jsonConfig) {
        JSONObject jsonObject = null;   
        try {    
            log.debug("json: " + jsonString);
            jsonObject = JSONObject.fromObject(jsonString, jsonConfig);   
        } catch(Exception e) {   
            e.printStackTrace();   
        }
        return jsonObject;
    }
    
    /**  
     * 从一个JSON 对象字符格式中得到一个java对象，形如：  
     * {"id" : idValue, "name" : nameValue, "aBean" : {"aBeanId" : aBeanIdValue, ...}}  
     * @param object  
     * @param clazz  
     * @return  
     */  
    public static Object getDTO(String jsonString, Class clazz){   
        JSONObject jsonObject = getJSONObject(jsonString);
        return JSONObject.toBean(jsonObject, clazz);   
    }   

    /**  
     * 从一个JSON 对象字符格式中得到一个java对象 ，形如：  
     * {"id" : idValue, "name" : nameValue, "aBean" : {"aBeanId" : aBeanIdValue, ...}}  
     * @param object  
     * @param jsonConfig  
     * @return  
     */  
    public static Object getDTO(String jsonString, JsonConfig jsonConfig){   
        JSONObject jsonObject = getJSONObject(jsonString, jsonConfig);
        return JSONObject.toBean(jsonObject, jsonConfig);   
    }
    
    /**  
     * 从一个JSON 对象字符格式中得到一个java对象，其中map是一类的集合，形如：  
     * {"id" : idValue, "name" : nameValue, "aBean" : {"aBeanId" : aBeanIdValue, ...},  
     * map:[{}, {}, ...]}  
     * @param jsonString  
     * @param clazz  
     * @param map 集合属性的类型 (key : 集合属性名, value : 集合属性类型class) eg: ("beansList" : Bean.class)  
     * @return  
     */  
    public static Object getDTO(String jsonString, Class clazz, Map map){   
        JSONObject jsonObject = getJSONObject(jsonString); 
        return JSONObject.toBean(jsonObject, clazz, map);   
    }   
       
    /**  
     * 从一个JSON数组得到一个java对象数组，形如：  
     * [{"id" : idValue, "name" : nameValue}, {"id" : idValue, "name" : nameValue}, ...]  
     * @param jsonString  
     * @param clazz  
     * @return  
     */  
    public static Object[] getDTOArray(String jsonString, Class clazz){   
        log.debug("json: " + jsonString);
        JSONArray array = JSONArray.fromObject(jsonString);   
        Object[] obj = new Object[array.size()];   
        for(int i = 0; i < array.size(); i++){   
            JSONObject jsonObject = array.getJSONObject(i);   
            obj[i] = JSONObject.toBean(jsonObject, clazz);   
        }   
        return obj;   
    }   
    
    /**  
     * 从一个JSON数组得到一个java对象数组，形如：  
     * [{"id" : idValue, "name" : nameValue}, {"id" : idValue, "name" : nameValue}, ...]  
     * @param jsonString  
     * @param jsonConfig  
     * @return  
     */  
    public static Object[] getDTOArray(String jsonString, JsonConfig jsonConfig){   
        log.debug("json: " + jsonString);
        JSONArray array = JSONArray.fromObject(jsonString, jsonConfig);   
        Object[] obj = new Object[array.size()];   
        for(int i = 0; i < array.size(); i++){   
            JSONObject jsonObject = array.getJSONObject(i);   
            obj[i] = JSONObject.toBean(jsonObject, jsonConfig);   
        }   
        return obj;   
    } 
    
    /**  
     * 从一个JSON数组得到一个java对象数组，形如：  
     * [{"id" : idValue, "name" : nameValue}, {"id" : idValue, "name" : nameValue}, ...]  
     * @param jsonString  
     * @param clazz  
     * @param map  
     * @return  
     */  
    public static Object[] getDTOArray(String jsonString, Class clazz, Map map){     
        log.debug("json: " + jsonString);
        JSONArray array = JSONArray.fromObject(jsonString);   
        Object[] obj = new Object[array.size()];   
        for(int i = 0; i < array.size(); i++){   
            JSONObject jsonObject = array.getJSONObject(i);   
            obj[i] = JSONObject.toBean(jsonObject, clazz, map);   
        }   
        return obj;   
    }   
       
    /**  
     * 从一个JSON数组得到一个java对象集合  
     * @param object  
     * @param clazz  
     * @return  
     */  
    @SuppressWarnings("unchecked")
    public static List getDTOList(String jsonString, Class clazz){   
        log.debug("json: " + jsonString);
        JSONArray array = JSONArray.fromObject(jsonString);   
        List list = new ArrayList();   
        for(Iterator iter = array.iterator(); iter.hasNext();){   
            JSONObject jsonObject = (JSONObject)iter.next();   
            list.add(JSONObject.toBean(jsonObject, clazz));   
        }   
        return list;   
    }   
    
    /**  
     * 从一个JSON数组得到一个java对象集合  
     * @param object  
     * @param jsonConfig  
     * @return  
     */ 
    @SuppressWarnings("unchecked")
    public static List getDTOList(String jsonString, JsonConfig jsonConfig){   
        log.debug("json: " + jsonString);
        JSONArray array = JSONArray.fromObject(jsonString, jsonConfig);   
        List list = new ArrayList();   
        for(Iterator iter = array.iterator(); iter.hasNext();){   
            JSONObject jsonObject = (JSONObject)iter.next();   
            list.add(JSONObject.toBean(jsonObject, jsonConfig));   
        }   
        return list;   
    } 
    
    /**  
     * 从一个JSON数组得到一个java对象集合，其中对象中包含有集合属性  
     * @param object  
     * @param clazz  
     * @param map 集合属性的类型  
     * @return  
     */  
    @SuppressWarnings("unchecked")
    public static List getDTOList(String jsonString, Class clazz, Map map){    
        log.debug("json: " + jsonString);
        JSONArray array = JSONArray.fromObject(jsonString);   
        List list = new ArrayList();   
        for(Iterator iter = array.iterator(); iter.hasNext();){   
            JSONObject jsonObject = (JSONObject)iter.next();   
            list.add(JSONObject.toBean(jsonObject, clazz, map));   
        }   
        return list;   
    }   
       
    /**  
     * 从json HASH表达式中获取一个map，该map支持嵌套功能  
     * 形如：{"id" : "johncon", "name" : "小强"}  
     * 注意commons-collections版本，必须包含org.apache.commons.collections.map.MultiKeyMap  
     * @param jsonString  
     * @return  
     */
    public static Map getMapFromJson(String jsonString) {     
        JSONObject jsonObject = getJSONObject(jsonString); 
        return convertJSONObject2Map(jsonObject); 
    }   
    
    /**  
     * 从json HASH表达式中获取一个map，该map支持嵌套功能  
     * 形如：{"id" : "johncon", "name" : "小强"}  
     * 注意commons-collections版本，必须包含org.apache.commons.collections.map.MultiKeyMap  
     * @param jsonString  
     * @param jsonConfig 
     * @return  
     */ 
    public static Map getMapFromJson(String jsonString, JsonConfig jsonConfig) {     
        JSONObject jsonObject = getJSONObject(jsonString, jsonConfig);   
        return convertJSONObject2Map(jsonObject);   
    } 

    @SuppressWarnings("unchecked")
    private static Map convertJSONObject2Map(JSONObject jsonObject) {
        Map map = new HashMap();   
        if(jsonObject == null) {
            return map;
        }
        for(Iterator iter = jsonObject.keys(); iter.hasNext();){   
            String key = (String)iter.next();   
            map.put(key, jsonObject.get(key));   
        }   
        return map;   
    }
    
    /**  
     * 从json数组中得到相应java基本类型数组  
     * json形如：["123", "456"]  
     * @param jsonString  
     * @return  
     */  
    public static Object[] getObjectArrayFromJson(String jsonString) { 
        //LogUtil.debug(JsonUtil.class, "json: " + jsonString);
        JSONArray jsonArray = JSONArray.fromObject(jsonString);   
        return jsonArray.toArray();   
    }   
  
    /**  
     * 从json数组中得到相应java基本类型数组  
     * json形如：["123", "456"]  
     * @param jsonString  
     * @param jsonConfig
     * @return  
     */  
    public static Object[] getObjectArrayFromJson(String jsonString, JsonConfig jsonConfig) { 
        //LogUtil.debug(JsonUtil.class, "json: " + jsonString);
        JSONArray jsonArray = JSONArray.fromObject(jsonString, jsonConfig);   
        return jsonArray.toArray();   
    }   
    
    /**  
     * 把数据对象转换成json字符串  
     * DTO对象形如：{"id" : idValue, "name" : nameValue, ...}  
     * 数组对象形如：[{}, {}, {}, ...]  
     * map对象形如：{key1 : {"id" : idValue, "name" : nameValue, ...}, key2 : {}, ...}  
     * @param object  
     * @return  
     */  
    public static String getJSONString(Object object) {   
        return getJSONString(object, null);   
    }   
    
    /**  
     * 把数据对象转换成json字符串  
     * DTO对象形如：{"id" : idValue, "name" : nameValue, ...}  
     * 数组对象形如：[{}, {}, {}, ...]  
     * map对象形如：{key1 : {"id" : idValue, "name" : nameValue, ...}, key2 : {}, ...}  
     * @param object 要转换成json字符串的对象
     * @param datePattern 指定的日期转换目标格式，默认为yyyy-MM-dd HH:mm:ss
     * @return  
     */  
    @SuppressWarnings("unchecked")
    public static String getJSONString(Object object, String datePattern) { 
        if ( object == null) {
            return "{}";
        }
        
        String jsonString = null;   
        //注册日期值处理器，Java.util.Date转换成Json格式的日期时使用，默认格式：yyyy-MM-dd HH:mm:ss
        JsonConfig jsonConfig = configJson(datePattern);   
        if(object != null){   
            if(object instanceof Collection || object instanceof Object[]){   
                jsonString = JSONArray.fromObject(object, jsonConfig).toString();   
            }else{   
                jsonString = JSONObject.fromObject(object, jsonConfig).toString();   
            }   
        }   
        log.debug("json: " + jsonString);
        return jsonString == null ? "{}" : jsonString;  
    }

    /**  
     * 根据参数组装返回前台的Json字符串
     * 结果字符串格式为："{\"result\":\"success\",\"msg\":\"客户资料保存成功！\"}" 
     *  
     * @param successOrFail  String
     * @param msg   String
     * @return  String 返回前台的Json格式字符串
     */  
    public static String getJSONRespStr(String successOrFail, String msg) { 
        
        String jsonString = "{\"result\":\"fail\",\"msg\":\"返回消息为空！\"}" ;       
        if ( !("success".equals(successOrFail) || "fail".equals(successOrFail) ) ) {
            return jsonString;
        }
        if ( msg == null) {
            return jsonString;
        }
        
        JSONObject jsonObject = JSONObject.fromObject(jsonString);
        jsonObject.put("result", successOrFail);
        jsonObject.put("msg", msg);
        
        jsonString = jsonObject.toString();
        //LogUtil.debug(JsonUtil.class, "组装的应答信息: " + jsonString);
        
        return jsonString == null ? "{}" : jsonString;   
    }    
    /**
    * JSON配置，用于配置默认的时间解析器等
    * @return
    */
    public static JsonConfig configJson() {
        return configJson(new String[]{""});
    }

    /**
    * @param excludes 不需要解析的字段
    * @return
    */
    public static JsonConfig configJson(String[] excludes) { 
        return configJson(excludes, null);
    }

    /**
    * @param objectClass 集合中包含的对象的Class
    * @return
    */
    public static JsonConfig configJson(Class objectClass) { 
        return configJson(new String[]{""}, objectClass);
    }
    
    /**
     * @param excludes 不需要解析的字段
     * @param objectClass 集合中包含的对象的Class
     * @return
     */
    public static JsonConfig configJson(String[] excludes, Class objectClass) {
        JsonConfig jsonConfig = new JsonConfig();
        if (objectClass != null) {
            jsonConfig.setRootClass(objectClass);
        }
        jsonConfig.setExcludes(excludes);
        jsonConfig.setIgnoreDefaultExcludes(false);
        jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
        jsonConfig.registerJsonValueProcessor(java.util.Date.class, new JsonDateValueProcessor());
        jsonConfig.registerDefaultValueProcessor(Long.class,new NumberProcessor());
        jsonConfig.registerDefaultValueProcessor(Integer.class,new NumberProcessor());
        return jsonConfig;
    }
    
    /**
     * 默认日期格式为："yyyy-MM-dd HH:mm:ss"，如需要其他格式，可通过此方法进行设置
     * 
     * @param datePattern 日期格式，如"yyyy-MM-dd"
     * @return JsonConfig
     */
    public static JsonConfig configJson(String datePattern) {       
        JsonConfig jsonConfig = configJson();
        if(!StringUtils.hasText(datePattern)) {
            return jsonConfig;
        }
        
        jsonConfig.registerJsonValueProcessor(java.util.Date.class, new JsonDateValueProcessor(datePattern));
        jsonConfig.registerDefaultValueProcessor(Long.class,new NumberProcessor());
        jsonConfig.registerDefaultValueProcessor(Integer.class,new NumberProcessor());
        return jsonConfig;
    }
    
    private static void setJsonDataFormat(){   
        //注册日期串的处理格式列表，在Json格式的日期转换到Java.util.Date时使用
//      JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String[] {"yyyy-MM-dd HH:mm:ss","yyyy-MM-dd"}));
    } 
    
    /***************************************************************************
     * @author:gaojm
     * @dateTime:2011-02-10 13:30:30
     * @param:
     * @return:void
     * @describe:递归方法，把含有树形结构的list转换成json格式字符字符串
     **************************************************************************/
    
    public void recursionFn(List<Node> list , Node node){
        if(hasChild(list,node)){    
            returnStr.append("{\"id\":");  
            returnStr.append(node.getId());  
            if (node.getChecked()!=null){
                returnStr.append(",\"checked\":");  
                returnStr.append(node.getChecked());        
            }
/*          returnStr.append(",\"parentId\":");  
            returnStr.append(node.getParentId());
            returnStr.append(",\"level\":");  
            returnStr.append(node.getLevel());*/
            
            if(StringUtils.hasText(node.getLevel())) {
                if("1".equals(node.getLevel())) {
                    returnStr.append(",\"state\":");  
                    returnStr.append("\"open\"");
                }else {
                    returnStr.append(",\"state\":");  
                    returnStr.append("\"closed\"");
                }
            }
            
            returnStr.append(",\"text\":");  
            returnStr.append("\"").append(node.getText()).append("\"");  
            returnStr.append(",\"attributes\":");  
            returnStr.append(JsonUtil.getJSONString(node.getAttributes()));  
            returnStr.append(",\"children\":[");    
            List childList = getChildList(list,node);    
            Iterator it = childList.iterator();    
            while(it.hasNext()){ 
                Node n = (Node)it.next();    
                recursionFn(list,n);    
            }
            returnStr.append("]},");    
        }else{    
            returnStr.append("{\"id\":");  
            returnStr.append(node.getId());  
            if (node.getChecked()!=null){
                returnStr.append(",\"checked\":");  
                returnStr.append(node.getChecked());        
            }
/*            returnStr.append(",\"parentId\":");  
            returnStr.append(node.getParentId());
            returnStr.append(",\"level\":");  
            returnStr.append(node.getLevel());*/
            returnStr.append(",\"text\":");
            returnStr.append("\"").append(node.getText()).append("\""); 
            returnStr.append(",\"attributes\":");  
            returnStr.append(JsonUtil.getJSONString(node.getAttributes())); 
            returnStr.append("},");    
        }    
    }
    //判断是否有子节点  
    private boolean hasChild(List list, Node node){  
        return getChildList(list,node).size()>0?true:false;  
    } 
    //得到子节点列表  
    @SuppressWarnings("unchecked")
    private List getChildList(List list , Node node){ 
        List li = new ArrayList();    
        Iterator it = list.iterator();    
        while(it.hasNext()){    
            Node n = (Node)it.next();    
            if(n.getParentId().equals(node.getId())){    
                li.add(n);    
            }    
        }
        return li;    
    } 
   //修饰一下才能满足Json格式  
    public String modifyNodeListStr(List<Node> list){
        for(Node rootNode : list){
            if("1".equals(rootNode.getLevel())){
                recursionFn(list,rootNode);
            }
        }
        String str = returnStr.toString();
        return ("["+str+"]").replaceAll(",]", "]");  
    }
    
    /**
     * 传入任意一个 object对象生成一个指定规格的字符串
     * 
     * @param object 任意对象
     * @return String
     */
    public static String objectToJson(Object object) {
        StringBuilder json = new StringBuilder();
        if (object == null) {
            json.append("\"\"");
        } else if (object instanceof String || object instanceof Integer || object instanceof Double) {
            json.append("\"").append(object.toString()).append("\"");
        } else {
            json.append(beanToJson(object));
        }
        return json.toString();
    }

    /**
     * 传入任意一个 Javabean对象生成一个指定规格的字符串
     * 
     * @param bean bean对象
     * @return String "{}"
     */
    public static String beanToJson(Object bean) {
        StringBuilder json = new StringBuilder();
        json.append("{");
        PropertyDescriptor[] props = null;
        try {
            props = Introspector.getBeanInfo(bean.getClass(), Object.class).getPropertyDescriptors();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (props != null) {
            for (int i = 0; i < props.length; i++) {
                try {
                    String name = objectToJson(props[i].getName());
                    String value = objectToJson(props[i].getReadMethod().invoke(bean));
                    json.append(name);
                    json.append(":");
                    json.append(value);
                    json.append(",");
                } catch (Exception e) {
                }
            }
            json.setCharAt(json.length() - 1, '}');
        } else {
            json.append("}");
        }
        return json.toString();
    }

    /**
     * 通过传入一个列表对象,调用指定方法将列表中的数据生成一个JSON规格指定字符串
     * 
     * @param list 列表对象
     * @return String "[{},{}]"
     */
    public static String listToJson(List<?> list) {
        StringBuilder json = new StringBuilder();
        json.append("[");
        if (list != null && list.size() > 0) {
            for (Object obj : list) {
                json.append(objectToJson(obj));
                json.append(",");
            }
            json.setCharAt(json.length() - 1, ']');
        } else {
            json.append("]");
        }
        return json.toString();
    }
    
    //json默认会把Number类型的null转换为0，注册此处理器，可使其仍然转换为null
    static class NumberProcessor implements DefaultValueProcessor {    
        @Override
		public Object getDefaultValue(Class type) {    
            return null;    
        }    
    }
}   
